package com.bjkcst.baselib.protocolparse;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;

/**
 * Created by yangjinfa on 3/04/18.
 * 一些单独的方法类，先收集在这里  DataProcessUtils
 */

public class DataProcessUtils {

    private final static String TAG = "DataProcessUtils";

    public static int ToDecimalByHex(String hexData) {
        return Integer.parseInt(hexData, 16);
    }

    public static String ToHexStrByOneByte(byte b) {
        String sTemp = Integer.toHexString(0xFF & b);
        if (sTemp.length() < 2) {
            sTemp = "0" + sTemp;
        }
        return sTemp;
    }

    /**
     * 求校验和的算法
     *
     * @param b 需要求校验和的字节数组
     * @return 校验和
     */
    public static byte SumCheck(byte[] b, int len) {
        int sum = 0;
        for (int i = 0; i < len; i++) {
            sum = sum + b[i];
        }
        if (sum > 0xff) { //超过了255，使用补码（补码 = 原码取反 + 1）
            sum = ~sum;
            sum = sum + 1;
        }
        return (byte) (sum & 0xff);
    }

    public static String MakeChecksum(String data) {
        if (data == null || data.equals("")) {
            return "";
        }
        int total = 0;
        int len = data.length();
        int num = 0;
        while (num < len) {
            String s = data.substring(num, num + 2);
            total += Integer.parseInt(s, 16);
            num = num + 2;
        }
        /*
         * 用256求余最大是255，即16进制的FF
         * */
        int mod = total % 256;
        String hex = Integer.toHexString(mod);
        len = hex.length();
        // 如果不够校验位的长度，补0,这里用的是两位校验
        if (len < 2) {
            hex = "0" + hex;
        }
        return hex.toUpperCase();
    }


    /**
     * 十进制转换成二进制，高位补零
     *
     * @param i     十进制数字
     * @param lenth 二进制长度
     * @return 二进制数组
     */
    public static char[] ToBinaryString(int i, int lenth) {
        char[] digits = {'0', '1'};
        char[] buf = new char[lenth];
        int pos = lenth;
        int mask = 1;
        do {
            buf[--pos] = digits[i & mask];
            i >>>= 1;
        } while (pos > 0);

        return new String(buf, pos, lenth).toCharArray();
    }

    /**
     * 十六进制字符串转换成字符串
     *
     * @param hexStr
     * @return String
     */
    public static String hexStr2Str(String hexStr) {
        String str = "0123456789ABCDEF";
        char[] hexs = hexStr.toCharArray();
        byte[] bytes = new byte[hexStr.length() / 2];
        int n;
        for (int i = 0; i < bytes.length; i++) {
            n = str.indexOf(hexs[2 * i]) * 16;
            n += str.indexOf(hexs[2 * i + 1]);
            bytes[i] = (byte) (n & 0xff);
        }
        return new String(bytes);
    }

    /**
     * 十六进制字符串转换字符串
     *
     * @param s
     * @return String
     */
    public static String toStringHex(String s) {
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(
                        i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            s = new String(baKeyword, "utf-8");// UTF-16le:Not
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return s;
    }

    /**
     * 数组转换成十六进制字符串
     *
     * @param bArray
     * @return HexString
     */
    public static String BytesToHexString(byte[] bArray) {
        StringBuilder sb = new StringBuilder(bArray.length);
        String sTemp;
        for (int i = 0; i < bArray.length; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2) {
                sb.append(0);
            }
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }


    /**
     * 数组转换成十六进制字符串
     *
     * @param bArray
     * @return HexString
     */
    public static String BytesToHexString(byte[] bArray, int size) {
        StringBuilder sb = new StringBuilder(bArray.length);
        String sTemp;
        for (int i = 0; i < size; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2) {
                sb.append(0);
            }
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 把16进制字符串转换成字节数组
     *
     * @param hex
     * @return byte[]
     */
    public static byte[] hexStringToByte(String hex) {
        int len = (hex.length() / 2);
        byte[] result = new byte[len];
        char[] achar = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }
        return result;
    }


//    public static String ToHexStrByOneByte(byte b) {
//        return Integer.toHexString(0xFF & b);
//    }


    /**
     * 字符串转换成十六进制字符串
     */
    public static String str2HexStr(String str) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;
        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
        }
        return sb.toString();
    }

    private static int toByte(char c) {
        byte b = (byte) "0123456789ABCDEF".indexOf(c);
        return b;
    }

    /**
     * i 从 0 开始
     * @param b
     * @param i
     * @return
     */
    public static int getBit(byte b,int i) {
        int bit = (int)((b>>i) & 0x1);
        return bit;
    }

    public static int[] getBits(byte b,int ... ints){
        int[] aars = new int[ints.length];
        for (int i = 0; i < ints.length; i++) {
            int anInt = ints[i];
            if (anInt > 7){continue;}
            int bit = (int)((b>>anInt) & 0x1);
            aars[i] = bit;
        }
        return aars;
    }

    /**
     * byte数值转成字符串
     * @param bytes
     * @return
     */
    public static String byteToBitStr(byte[] bytes){
        StringBuffer sb = new StringBuffer();
        for (byte aByte : bytes) {
            String s = byteToBit(aByte);
            sb.append(s);
        }
        return sb.toString();
    }

    /**
     * bit 字符串转byte数组
     * @param bitValue
     * @return
     */
    public static byte[] bitToBytes(String bitValue){
        if (bitValue.length() % 8 != 0){return null;}
        int count = bitValue.length() / 8;
        byte[] bytes = new byte[count];
        for (int i = 0; i < bitValue.length(); i = i + 8) {
            String result = bitValue.substring(i, i + 8);
            byte b = bitToByte(result);
            bytes[i/8] = b;
        }
        return bytes;
    }

    /**
     * Byte转Bit
     */
    public static String byteToBit(byte b) {
        return "" +(byte)((b >> 7) & 0x1) +
                (byte)((b >> 6) & 0x1) +
                (byte)((b >> 5) & 0x1) +
                (byte)((b >> 4) & 0x1) +
                (byte)((b >> 3) & 0x1) +
                (byte)((b >> 2) & 0x1) +
                (byte)((b >> 1) & 0x1) +
                (byte)((b >> 0) & 0x1);
    }

    /**
     * Bit转Byte
     */
    public static byte bitToByte(String byteStr) {
        int re, len;
        if (null == byteStr) {
            return 0;
        }
        len = byteStr.length();
        if (len != 4 && len != 8) {
            return 0;
        }
        if (len == 8) {// 8 bit处理
            if (byteStr.charAt(0) == '0') {// 正数
                re = Integer.parseInt(byteStr, 2);
            } else {// 负数
                re = Integer.parseInt(byteStr, 2) - 256;
            }
        } else {//4 bit处理
            re = Integer.parseInt(byteStr, 2);
        }
        return (byte) re;
    }


    /**
     * 获取单独一位的BIT数据(0-7)
     *
     * @param hex      16进制的字符串数据
     * @param bitIndex 第几位
     * @return true=1 false=0
     */
    public static boolean getOneBit(String hex, int bitIndex) {
        if (bitIndex < 0 || bitIndex > 7) {
            return false;
        }

        int data = Integer.parseInt(hex, 16);
        return (((data & ((int) (Math.pow(2, bitIndex)))) >> bitIndex) == 1);
    }


    public static int getOneBitValue(String hex, int bitIndex) {
        if (bitIndex < 0 || bitIndex > 7) {
            return 0;
        }

        int data = Integer.parseInt(hex, 16);
        return (((data & ((int) (Math.pow(2, bitIndex)))) >> bitIndex));
    }



    public static int[] getBitValue(byte b){
        int[] value = new int[8];
        for (int i = 0; i < value.length; i++) {
            value[i] = getOneBitValue(b,i);
        }
        return value;
    }

    public static int getOneBitValue(byte b, int bitIndex) {
        int data = b & 0xFF;
        return (((data & ((int) (Math.pow(2, bitIndex)))) >> bitIndex));
    }

    /**
     * add by liangjuan@20200728
     * 用于依据最高位，将两个pwm互斥量（即要么小的存在要么大的存在）合并成对照的十六进制字符串
     *
     * @param smallPwm：待转换的低位PWM
     * @param bigPwm：待转换的高位PWM
     * @param HighByte：默认的高位最大值  以默认最高位FF为例，其中位是7F，那么待转换的低位PWM就是转成0-7F，待转换的高位PWM就转成是7F-FF
     */
    public static String MixOneByte(int smallPwm, int bigPwm, String HighByte) {
        int HighNo = Integer.parseInt(HighByte, 16);
        int HalfNo = HighNo / 2;
        String mByte = "7f";
        if (smallPwm > bigPwm) {
            mByte = Integer.toHexString(((HalfNo - smallPwm * HalfNo / 100)) & 0XFF);
        } else if (bigPwm > smallPwm) {
            mByte = Integer.toHexString(((bigPwm * HalfNo / 100) & 0XFF) | 1 << 7);
        }
        if (mByte.length() < 2) {
            mByte = mByte + "0";
        }
        return mByte;
    }

    /**
     * add by liangjuan@20200728
     * 用于依据最高位，将一个PWM改成按照最高位对照的十六进制字符串
     *
     * @param pwm：待转换的PWM值
     * @param smallFlag：是向低位转还是高位转
     * @param HighByte：默认的高位最大值    以默认最高位FF为例，其中位是7F，那么向低位转就是转成0-7F，向高位转就是7F-FF
     * @return
     */
    public static String MixOneByte(int pwm, boolean smallFlag, String HighByte) {
        int HighNo = Integer.parseInt(HighByte, 16);
        if (smallFlag) {
            return Integer.toHexString(pwm / 100 * HighNo & 0xff);
        } else {
            return Integer.toHexString((pwm / 100 * HighNo + HighNo) & 0xff);
        }
    }

    /**
     * 计算数据校验和
     * @param check
     * @return
     */
    public static String getCheckSum(byte[] check){
        int sum=0;
        for(int i =0; i < check.length; i++) {
            sum += check[i] & 0xFF;
        }
        return String.format("%02x", sum & 0xFF);
    }

    public static int getCheckSumNum(byte[] check){
        int sum=0;
        for(int i =0; i < check.length; i++) {
            sum += check[i] & 0xFF;
        }
        return sum;
    }

    /**
     * crc校验
     * @param packet 完整的数据包
     * @return
     */
    public static boolean checkCrc(byte[] packet){
        if(packet == null || packet.length < 2){
            return false;
        }
        int packLenth = packet.length;
        int sum = 0;
        for(int i = 0; i < packet.length - 1; i++){
            sum += packet[i] & 0xFF;
        }
        String crc = String.format("%02x", sum & 0xFF);
        String lastByte = String.format("%02x", packet[packLenth - 1] & 0xFF);
        return lastByte.equalsIgnoreCase(crc);
    }

    /**
     * 长度校验  2-3字节为包长度      减去4字节 =  起始字符（1byte）+ 包长度（2byte）+ crc校验位（1字节）
     * @param bytes
     * @return
     */
    public static boolean checkPackageLength(byte[] bytes){
        byte[] bytes1 = Arrays.copyOfRange(bytes, 1, 3);
        int countPackageLength = DataProcessUtils.byteToInt2(bytes1);
        return countPackageLength == bytes.length - 4;
    }

    /**
     * 16进制形式的字符串转换为16进制的字节数组
     * @param s
     * @return
     */
    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }

    public static long bytesToLong(byte[] bytes) {
        if(bytes.length == 1){
            return bytes[0];
        }else if(bytes.length == 2){
            return bytes[0] * 256 +  byte2Int(bytes[1]);
        }else if(bytes.length == 3){
            return bytes[0] * 65536 +  byte2Int(bytes[1]) * 256 + byte2Int(bytes[2]);
        }else if(bytes.length == 4){
            return bytes[0] * 16777216 + byte2Int(bytes[1]) * 65536 + byte2Int(bytes[2]) * 256 + byte2Int(bytes[3]);
        }else if(bytes.length == 5){
            return bytes[0] * 4294967296l + byte2Int(bytes[1]) * 16777216 + byte2Int(bytes[2]) * 65536 + byte2Int(bytes[3]) * 256 +  byte2Int(bytes[4]);
        }else if(bytes.length == 6){
            return bytes[0] * 1099511627776l + byte2Int(bytes[1]) * 4294967296l + byte2Int(bytes[2]) * 16777216 + byte2Int(bytes[3]) * 65536 + byte2Int(bytes[4]) * 256 +  byte2Int(bytes[5]);
        }else if(bytes.length == 7){
            return bytes[0] * 281474976710656l + byte2Int(bytes[1]) * 1099511627776l + byte2Int(bytes[2]) * 4294967296l + byte2Int(bytes[3]) * 16777216 + byte2Int(bytes[4]) * 65536 + byte2Int(bytes[5]) * 256 +  byte2Int(bytes[6]);
        }
        return 0l;
    }

    public static int byte2Int(byte b){
        return (int)(b & 0xff);
    }

    public static String byte2hex(byte[] buffer){
        String h = "";
        for(int i = 0; i < buffer.length; i++){
            String temp = Integer.toHexString(buffer[i] & 0xFF);
            if(temp.length() == 1){
                temp = "0" + temp;
            }
            h = h + " "+ temp;
        }
        return h;
    }

    public static short[] getShorts(byte[] bytes){
        if (bytes.length < 4){return new short[]{0,0};}
        short value1 = ByteBuffer.wrap(new byte[]{bytes[0],bytes[1]}).order(ByteOrder.LITTLE_ENDIAN).getShort(0);
        short value2 = ByteBuffer.wrap(new byte[]{bytes[2],bytes[3]}).order(ByteOrder.LITTLE_ENDIAN).getShort(0);
        return new short[]{value1,value2};
    }


    public static int byteToInt4(byte[] bArr){
        int value;
        value = (int)((((bArr[3] & 0xff) << 24)
                | ((bArr[2] & 0xff) << 16)
                | ((bArr[1] & 0xff) << 8)
                | ((bArr[0] & 0xff) << 0)));
        return value;
    }

    //大端序
    public static byte[] intToByte(int n){
        byte[] b = new byte[4];
        b[0] = (byte) (n & 0xff);
        b[1] = (byte) (n >> 8 & 0xff);
        b[2] = (byte) (n >> 16 & 0xff);
        b[3] = (byte) (n >> 24 & 0xff);
        return b;
    }

    /**
     * 小端模式
     * @param array
     * @return
     */
    public static int byteToInt2(byte[] array){
        int value = (int) (((array[1])<<8) | ((array[0] & 0xFF)));
        return value;
    }

    public static byte[] intToByte2(int n){
        byte[] b = new byte[2];
        b[0] = (byte) (n >> 8 & 0xff);
        b[1] = (byte) (n & 0xff);
        return b;
    }
}
